#pragma once
#include <iostream>
#include <cstdlib>
#include <string>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <memory>
#include <functional>
#include "InetAddr.hpp"
#include "Logger.hpp"
#include "Socket.hpp"
#include "Protocol.hpp"



//基于TcpSocket，通过Socket以实现多态
using callback_t = std::function<std::string(std::string&)>;
class TcpServer
{
    private:
    void HandlerRequest(std::shared_ptr<Socket> fd,InetAddr& client)
    {
        std::string inbuffer;
        //建立长连接服务
        while(true)
        {
            int n = fd->Recv(&inbuffer);
            if(n < 0)
            {
                LOG(LogLevel::FATAL) << "server read error";
                exit(READ_ERR);
            }
            else if(n == 0)
            {
                LOG(LogLevel::INFO) << client.ToString() << " quit connect";
                break;
            }
            else
            {
                //接收来的http请求
                LOG(LogLevel::INFO) << client.ToString() << ':' << inbuffer;
                //要确保数据接收的完整性
                if(!HttpRequest::IsComplete(inbuffer))
                    continue;
                // std::cout << "走到这里了" << std::endl;
                std::string send_str = _cb(inbuffer);
                if(send_str.empty())
                {
                    LOG(LogLevel::FATAL) << "server send_str _cb error";
                    exit(1);
                }
                // LOG(LogLevel::DEBUG) << "come here";
                fd->Send(send_str);
            }
        }
        fd->Close();
    }
    public:
    TcpServer(callback_t cb,uint16_t port = 8080):_tcp(std::make_unique<TcpSocket>()),_port(port),_cb(cb)
    {
        _tcp->BuildListenSocketMethod(_port);
        //完成好创建listen_socket,并且手动绑定的工作
    }

    void Start()
    {
        signal(SIGCHLD,SIG_IGN);
        //建立一个长服务
        while(true)
        {
            InetAddr client;
            auto fd = _tcp->Accept(&client);//拿到client的相关信息
            if(fd == nullptr)
                continue;
            
            //创建多进程以完成任务
            pid_t pid = fork();
            if(pid < 0)
            {
                LOG(LogLevel::FATAL) << "fork error";
                continue;
            }
            else if(pid == 0)
            {
                // _tcp->Close();
                HandlerRequest(fd,client);//服务端处理I/O请求，提取数据
                exit(0);//执行完后，正常退出即可
            }
            fd->Close();
        }
    }

    private:
    std::unique_ptr<Socket> _tcp;//用于listen_socket
    uint16_t _port;
    callback_t _cb;
};


